# -*- coding: utf-8 -*-
# © 2018 QYT Technology
import time
# import pickle
import os, re
from collections import OrderedDict
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from retrying import retry
import datetime
import configparser

class carSpider():
    history_number_list = OrderedDict()  # 左下历史记录  # FIXME: 修
    number_list = []
    browser = ''
    # rule_dict = {
    #     1: ['ball', ['follow_list'], ['value_list'], 'times', 'left'],
    # }
    origin_rule_list = []
    rule_list = []
    record_list = []
    add_record_list = []
    left_money = 0
    record = {}  # 用来计算中奖 其实好像没什么用 就是用来判断第一次中奖
    win_money = 0
    is_repeat = 0

    @retry
    def get_server(self, the_code):
        browser = webdriver.Chrome(path)
        browser.get(url)
        time.sleep(2)
        elem_code = browser.find_element_by_id('code')
        elem_code.send_keys(the_code)
        commit = browser.find_element_by_xpath('/html/body/form/div[2]/div[2]/input')
        commit.click()
        time.sleep(2)

        line_choice = browser.find_element_by_xpath('/html/body/div[3]/div/div[2]/table/tbody/tr/td[1]/a')
        link = line_choice.get_attribute("href")
        browser.get(link)
        time.sleep(2)
        return browser

    def __init__(self,the_code, username, password, key):
        ######直接初始化到赛车页面
        self.read_record()  # 可以单独调用
        self.read_rule()
        self.browser = self.get_server(the_code)
        self.login(username, password)
        self.xxxxx()
        self.agree()
        self.car_menu()
        # self.get_lottery_res()

    @retry
    def login(self, username, password):
        loginName = self.browser.find_element_by_id('loginName')
        loginName.send_keys(username)
        loginPwd = self.browser.find_element_by_id('loginPwd')
        loginPwd.send_keys(password)
        commit = self.browser.find_element_by_id('login_btn')
        time.sleep(2)
        commit.click()

    @retry
    def xxxxx(self):
        time.sleep(2)
        xxxxx = self.browser.find_element_by_xpath('//*[@id="myLayer_19841012"]/tbody/tr/td/div[1]/a')
        xxxxx.click()
        return True

    @retry
    def agree(self):
        agree = self.browser.find_element_by_xpath('/html/body/div[1]/div/div[3]/input[2]')
        agree.click()
        return True

    @retry
    def car_menu(self):
        # 要刷数据的时候先调用
        time.sleep(2)
        print('切换到汽车')
        self.browser.switch_to.default_content()
        menu = self.browser.find_element_by_id("menuText")
        car = self.browser.find_element_by_xpath('//*[@id="menuList"]/li[3]/a')
        ActionChains(self.browser).move_to_element(menu).click(car).perform()
        # 切换到的判断
        now_text = self.browser.find_element_by_xpath('//*[@id="menuText"]/span').text
        if now_text == '北京賽車(PK10)':
            return True
        else:
            raise Exception

    ###############下面是各种获取数据
    @retry
    def _get_lottery_res(self):  # TODO: 很多地方重复调用,优化
        # 获取开奖结果
        self.car_menu()
        time.sleep(2)
        print('获取开奖结果')
        time.sleep(2)
        try:
            self.browser.switch_to.frame("mainIframe")  # 切换到iframe
        except:
            pass
        now_number = self.browser.find_element_by_id('NowJq').text  # 当前期数
        number = self.browser.find_element_by_id('newPhase').text  # 期数
        while int(now_number) - int(number) > 1:
            now_number = self.browser.find_element_by_id('NowJq').text  # 当前期数
            number = self.browser.find_element_by_id('newPhase').text  # 期数
            time.sleep(2)
        self.number_list = []
        for i in range(1, 11):
            value = int(self.browser.find_element_by_xpath(
                '//*[@id="prevBall"]/span[%d]' % (i)).get_attribute("class").split('_')[1])
            if int(value) == 10:
                value = 0
            self.number_list.append(value)
        # 期号判断 停止再开启 有可能跳期
        # [int(number) + 1, rule_serial+1, rank + 1, self.list_to_str(rule[1]), value, rule[3], '', '']
        for add_record in self.add_record_list:
            # rule = self.rule_list[add_record[1]-1]
            if add_record[0] == int(number):
                rank = add_record[2]
                win_num = self.number_list[rank-1]
                if str(win_num) in add_record[3]:
                    state = '中'
                else:
                    state = '挂'
                add_record[6] = win_num
                add_record[7] = state
        print(self.number_list, self.add_record_list)
        return number, self.number_list, self.add_record_list


    def get_lottery_res(self, date_time='2018-08-08'):
        """for test"""
        history_list = self.read_history(date_time)
        history_list.reverse()
        self.history_ger = (i for i in history_list)
        return self.history_ger

    def test_lottery_res(self):
        """for test"""
        history = self.history_ger.__next__()
        history = history.split(',')
        if '-------' not in history[1]:
            number = int(history[1])
            self.number_list = [int(i) for i in history[2].strip('\n')]
        print('--------------------------%s,%s'%(number, str(self.number_list)))
        return number, self.number_list

    def get_left_money(self):
        """
        获取余额
        """
        self.browser.switch_to.default_content()  # 切回
        self.left_money = self.browser.find_element_by_id('usableCreditSpan').text  # 可用余额
        return self.left_money

    @retry
    def get_left_time(self):
        """
        获取当前剩余时间
        :return:
        """
        print('获取剩余时间')
        try:
            self.browser.switch_to.frame("mainIframe")  # 切换到iframe
        except:
            pass
        text = self.browser.find_element_by_id('closeText').text
        self.win_money = self.browser.find_element_by_id('profit').text  # 今日输赢
        close_time = self.browser.find_element_by_id('closedTime').text  # 剩余时间
        close_time = re.findall('(\d{2})分(\d*)秒', close_time)
        left_second = int(close_time[0][0]) * 60 + int(close_time[0][1])
        print('剩余时间%s'%left_second)
        if text == '封盤':
            return True, left_second
        else:
            return False, left_second

    @retry
    def set_history_data(self):
        number, number_list, add_record_list = self._get_lottery_res()
        left_money = self.get_left_money()
        if number not in self.history_number_list:
            self.history_number_list[number] = (number_list, left_money)
        print(self.history_number_list)
        return self.history_number_list

    @retry
    def switch_car_iframe(self):
        # 切换到赛车 单球投注页
        print('切换到单球投注页')
        try:
            self.browser.switch_to.frame("mainIframe")  # 切换到iframe
        except:
            pass
        single_ball = self.browser.find_element_by_xpath('/html/body/div[2]/div[2]/div[1]/div[1]/div/div[1]/ul/li[2]/a')
        single_ball.click()
        time.sleep(3)

    @classmethod
    def _inw_axis(self):
        # 投注框坐标 第七名是 序列规则改变
        # 1 5 9 13 17 21 24  27 30 33
        # 1-10 17-26 33-42
        axis = {}
        y_axis = []
        n = 1
        for _ in range(0, 6):
            tmp = []
            for i in range(n, n+10):
                tmp.append(i)
            y_axis.append(tmp)
            n += 16

        n = 95
        for _ in range(0, 4):
            tmp = []
            for i in range(n, n+10):
                tmp.append(i)
            y_axis.append(tmp)
            n += 14

        for n, i in enumerate(range(1, 22, 4)):
            axis[i] = y_axis[n]
        for n, i in enumerate(range(24, 34, 3)):
            axis[i] = y_axis[n+6]
        return axis

    def _generate_inw(self, x, y):
        """
        :param x: 名次 不用-1 获取名次时已经减了
        :param y: 号码
        """
        y -= 1
        x = [1, 5, 9, 13, 17, 21, 24, 27, 30, 33][x]
        axis = self._inw_axis()
        return (x, axis[x][y])

    def _set_amount(self, x, y, value):
        # 设置投注金额
        axis = self._generate_inw(x, y)
        input = self.browser.find_element_by_xpath('//*[@id="inw_%d_%d"]/input'%axis)
        input.send_keys(value)

    # @classmethod
    # def add_rule(cls, serial, ball, follow_list, value_list):
    #     cls.rule_dict[serial] = [ball, follow_list, value_list, 1, 0]
    #     cls.save_rule()

    # @classmethod
    # def save_rule(cls):
    #     with open(cls.rule_file, 'wb') as f:
    #         pickle.dump(cls.rule_dict, f)
    #
    # def read_rule(self):
    #     """
    #     初始化规则
    #     """
    #     try:
    #         with open(self.rule_file, 'rb') as f:
    #             self.rule_dict = pickle.load(f)
    #         return self.rule_dict
    #     except IOError:
    #         pass
    # TODO: 是否可以保存每次记录

    def read_rule(self):
        """
        初始化规则
        """
        try:
            with open(rule_file, 'r') as f:
                rule_list = f.readlines()
                for rule in rule_list:
                    rule = rule.split('\n')[0]
                    if rule:
                        rule = rule.split('|')
                        print(rule)
                        self.value_count = len(rule[2].split('-'))
                        self.origin_rule_list.append([rule[0], rule[1], rule[2]])
                        self.rule_list.append([int(rule[0]), [int(i) for i in rule[1]], rule[2].split('-'), 0, 0])
            return self.rule_list
        except IOError:
            pass

    def add_record(self, data):
        """
        add_record("dd, sada,1 ,1312")
        """
        data = str(data) + '\r\n'
        with open(record_file, 'a') as f:
            f.writelines(data)

    def add_rule_record(self, data, date_time):
        """
        add_record("dd, sada,1 ,1312")
        """
        data = str(data) + '\r\n'
        record_file = os.path.join(os.path.curdir, '%s_%s_rule_record.txt'%(date_time, self.value_count))

        with open(record_file, 'w') as f:
            f.writelines(data)

    @classmethod
    def read_record(cls):
        """
        初始化记录，可以先读
        record[:-1].split(',')
        """
        try:
            with open(record_file, 'r') as f:
                cls.record_list = f.readlines()
                return cls.record_list
        except IOError:
            pass

    def follow_rules(self, target_rule_list):
        """
        :param target_rule_list: 需要执行的规则序列号 这里的编号从0开始
        :return:
        """
        # target_rule_list = [i for i in range(100)]
        number, number_list, add_record_list = self._get_lottery_res()  # 期数，开奖号码
        self.add_record_list = []
        stop = False
        if self.is_repeat == int(number):  # 已经下过单
            return stop, self.rule_list, []
        for rule_serial in target_rule_list:
            self._adjust_winning(rule_serial, self.rule_list[rule_serial], number)
        try:
            self.adjust_times()  # 有规则超过11次
            rule_list = [self.rule_list[rule_serial] for rule_serial in target_rule_list]
            sum_rule_dict = self.sum_rule(rule_list)

            # if self.get_left_time():  # 如果没时间了 停止投注 目前前端判断
            #     return
            self.switch_car_iframe()
            count_v = 0
            for key, value in sum_rule_dict.items():
                rank = self.number_list.index(key)  # 名次x坐标
                for y,v in value.items():
                    count_v += v
                    self._set_amount(rank, y, v)
            print("本次投注: %s"%count_v)  # 本次投注金额
            submit = self.browser.find_element_by_id('gameSubmit')
            # submit.click()
            time.sleep(1)
            # submit2 = self.browser.find_element_by_xpath('//*[@id="myLayer_19841012"]/tbody/tr/td/div[3]/a[2]')
            # submit2.click()
            # 避免重复下单
            self.is_repeat = int(number)

            # 返回流水
            for rule_serial in target_rule_list:
                rule = self.rule_list[rule_serial]
                self.sub_value(rule)
                rank = self.number_list.index(rule[0])  # 名次x坐标
                value = int(rule[2][rule[3]-1])  # sub_value的时候把次数加一了，这里要取上次
                self.add_record("%s,%s,%s,%s,%s,%s,%s,%s" % (int(number) + 1, rule_serial+1, rank + 1,
                                                             self.list_to_str(rule[1]), value, rule[3], '', ''))  # 期号，规则序号(是否加1), 位置, 投注球, 金额, 手数
                self.add_record_list.append([int(number) + 1, rule_serial+1, rank + 1,
                                                            self.list_to_str(rule[1]), value, rule[3], '', ''])
                self.record[rule_serial] = [rank, rule[3], int(number) + 1]
        except Exception as e:
            print(e)
            stop = True
        data = ''
        for t in self.rule_list:
            data = data + str(t) + '\r\n'
        print(data)
        today = datetime.datetime.today()
        self.add_rule_record(data, today.strftime('%Y-%m-%d'))
        return stop, self.rule_list, self.add_record_list

    @classmethod
    def list_to_str(cls, enter_list):
        target_str = ''
        for i in enter_list:
            target_str += str(i)
        return target_str

    def sum_rule(self, rule_list):
        """
        整合投注
        :return:
        """
        rule_dict = {}
        for rule in rule_list:
            target_number = rule[0]
            target_rule = rule[1]
            value = int(rule[2][rule[3]])
            number_value_dict = {}

            exist_number_value_dict = rule_dict.get(target_number)
            if exist_number_value_dict:
                for index in target_rule:
                    count_value = exist_number_value_dict.get(index)
                    if count_value:
                        exist_number_value_dict[index] += value
                    else:
                        exist_number_value_dict[index] = value
            else:
                for index in target_rule:
                    number_value_dict[index] = value
                rule_dict[rule[0]] = number_value_dict
        return rule_dict

    # def follow_rule(self, rule_serial, number):
    #     print('开始投注')
    #     # self._adjust_winning(rule_serial, self.rule_list[rule_serial])
    #     return self._follow_rule(rule_serial, self.rule_list[rule_serial], number)

    def adjust_winning(self, target_rule_list):
        """
        刷规则盈利
        """
        print('刷规则盈利')
        number, number_list, add_record_list = self._get_lottery_res()  # 期数，开奖号码
        for rule_serial in target_rule_list:
            self._adjust_winning(rule_serial, self.rule_list[rule_serial], number)
            data = ''
            for t in self.rule_list:
                data = data + str(t) + '\r\n'
            print(data)
            today = datetime.datetime.today()
            self.add_rule_record(data, today.strftime('%Y-%m-%d'))
        return self.rule_list

    def adjust_times(self):
        for rule in self.rule_list:
            if rule[3] > self.value_count - 1:# 任意一条规则 12次表示认输 一切停止
                print("超过%s次"%self.value_count)
                raise Exception

    def sub_value(self, rule):
        """
        投注后减去本次成本
        """
        value = rule[2][rule[3]]  # 本次投注金额
        rule[4] = round(rule[4] - int(value) * 5, 2)  # 先扣掉投注的资金
        rule[3] += 1  # 次数+1

    def _adjust_winning(self, serial, rule, recent_number):
        """
        规则序列，规则，期号
        是否中奖
        ['ball', ['follow_list'], ['value_list'], 'times', 'left']
        :return:
        """
        if serial in self.record:  # 第一次是空的
            rank = self.record[serial][0]
            # 加入期号判断
            number = self.record[serial][2]
            if int(recent_number) == int(number):
                win_number = self.number_list[rank]
            else:
                win_number = '999999999'  # TODO：一般没取到才会这样，所以还要取历史数据
            value = rule[2][rule[3]-1]  # 上次投注金额 已经被+1
            if win_number in rule[1]:
                self.record[serial][1] = 0  # 重置次数
                rule[3] = 0
                rule[4] = round(rule[4] + int(value) * peilv, 2)

    def return_content(self):
        self.browser.switch_to.default_content()  # 切回

    def read_history(self, date_time):
        history_file = os.path.join(os.path.curdir, '%shistory.txt'%date_time)
        with open(history_file, 'r') as f:
            return f.readlines()


path = os.path.join(os.path.curdir, 'chromedriver')

config = configparser.ConfigParser()
config_ini = os.path.join(os.path.curdir, 'config1.ini')

config.read(config_ini)
config.items('DEFAULT')
url = config['DEFAULT']['url']
code = config['DEFAULT']['code']
username = config['DEFAULT']['username']
password = config['DEFAULT']['password']
line = int(config['DEFAULT']['line'])
peilv = float(config['DEFAULT']['peilv'])
rule_file = os.path.join(os.path.curdir, 'rule.txt')
record_file = os.path.join(os.path.curdir, 'record.csv')
number_result = os.path.join(os.path.curdir, 'number.csv')

if __name__ == "__main__":
    print(carSpider._inw_axis())
    path = os.path.join(os.path.curdir, 'chromedriver')
    # # '/Users/username/Downloads/chromedriver/.exe'
    #
    # config = configparser.ConfigParser()
    # config_ini = os.path.join(os.path.curdir, 'config1.ini')
    #
    # config.read(config_ini)
    # config.items('DEFAULT')
    # url = config['DEFAULT']['url']
    # code = config['DEFAULT']['code']
    # username = config['DEFAULT']['username']
    # password = config['DEFAULT']['password']
    # line = int(config['DEFAULT']['line'])
    # peilv = float(config['DEFAULT']['peilv'])
    #
    # car = carSpider()
    # car.set_history_data()
    # print(car.history_number_list)
    # car.get_left_time()

    # # 初始化
    # car = carSpider()
    #
    # # 定时器 re_time
    # # 刷左下角
    # history_number_list = car.set_history_data()
    # # 更新左下数据 history_number_list
    # # 刷盈利
    # res, rule_list = car.adjust_winning([])
    # # rule_list 更新右上规则
    # if res:
    #     pass # 停止所有行为 输惨了
    # # 循环投注
    # for i in []:
    #     record = car.follow_rule(1,1)
    #     # 更新右下数据
    #     res, left_time = car.get_left_time()
    #     if res:
    #         if left_time < 10:
    #             #剩下10s 就不投了
    #             re_time = left_time +30
    #             break
    #     else:
    #         re_time = left_time


    # car.get_lottery_res()
    # print(car.number, car.number_list)
    # car.follow_rules()
    # print(car.add_record_list)
    # 顺序